﻿//===============================================================================
// Magic OQL
//===============================================================================
// Copyright ?Magic Thought Corporation. All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// Richie (http://www.cnblogs.com/RicCC)
// March 10, 2008
//===============================================================================

using Antlr.Runtime;
using Antlr.Runtime.Tree;

namespace SQLAnalyticLibrary.Expressions.Predicate
{
    /// <summary>
    /// IN(value1, value2), IN(sub query)
    /// </summary>
    public class In : Expression
    {
        private int _childIndex = 0;

        public In(IToken t)
            : base(t)
        {
        }

        /// <summary>
        /// 1. NOT? IN LPAREN expressions_0 (COMMA expressions_1)* RPAREN
        ///     -> ^(IN ^(TextNode NOT? IN) expressions expressions_0 expressions_1*)
        /// 2. NOT? IN subQuery
        ///     -> ^(IN ^(TextNode NOT? IN) expressions subQuery)
        /// </summary>
        /// <param name="t"></param>
        public override void AddChild(Expression t)
        {
            if (t == null)
            {
                this.InternalAddChild(t);
                return;
            }
            if (this._childIndex == 0 && SQLAnalyticLibrary.Expressions.Text.IsText(t))
            {
                this.Token.Text = t.ToString();
                this._childIndex++;
                return;
            }
            //if (this._childIndex == 0 && SQLAnalyticLibrary.Expressions.Text.IsText(t._children[0]))
            //{
            //    this.Token.Text = t._children[0].ToString();
            //    t._children.Remove(t._children[0]);
            //    this._childIndex++;
            //}
            this.InternalAddChild(t);
        }

        public override Expression DupNode()
        {
            return new In(this.Token);
        }

        public override void VisitSql(ISqlVisitor visitor)
        {
            if (this._children == null || this._children.Count < 2)
            {
                visitor.Sql("1=0"); //this predicate is false, to solve the problem that client may pass in null value list.
                return;
            }
            this._children[0].VisitSql(visitor); //
            visitor.Space();
            visitor.Sql(this.ToString()); //IN keyword
            if (SelectStatement.IsSelectStatement(this._children[1]))
            {
                //IN(sub query)
                this._children[1].VisitSql(visitor);
            }
            else
            {
                //IN(value1, value2, ...)
                visitor.Sql("(");
                for (int i = 1; i < this._children.Count; i++)
                {
                    if (i != 1) visitor.Sql(",");
                    this._children[i].VisitSql(visitor);
                }
                visitor.Sql(")");
            }
        }

        internal static int TreeType
        {
            get
            {
                return OQLParser.IN;
            }
        }
    }
}
